Skip to content

[CORE-149029] Fix preferred affinity restart loop caused by atomic list merge semantics#269

Open
dobrerazvan wants to merge 6 commits into
masterfrom
CORE-149029-fix
Open

[CORE-149029] Fix preferred affinity restart loop caused by atomic list merge semantics#269
dobrerazvan wants to merge 6 commits into
masterfrom
CORE-149029-fix

Conversation

@dobrerazvan

Copy link
Copy Markdown

Description

Problem: When ScaleOps (or any admission controller) injects preferredDuringSchedulingIgnoredDuringExecution terms, Koperator restarts brokers in a loop. Root cause: those lists have no patchMergeKey in the k8s API types → strategic merge patch treats them atomically → external additions are removed on every reconcile. Same class of bug as tolerations (which already has an explicit fix).

Secondary issue: pods without the banzaicloud.com/last-applied annotation fall back to two-way merge, which also reverts admission-controller resource-request changes.

Fix:

  • ignorePreferredAffinities() CalculateOption — strips preferred affinity lists from both sides of the diff before the strategic merge runs. Applied unconditionally (same as the toleration fix). No opt-in flag.
  • Annotation backfill — writes the annotation on first encounter of an unannotated pod, restoring three-way merge semantics.

Required and resource-request management are unchanged. 12 new tests covering pure unit cases and full diff-level behaviour.

Type of Change

  • Bug Fix
  • New Feature
  • Breaking Change
  • Refactor
  • Documentation
  • Other (please describe)

Checklist

  • I have read the contributing guidelines
  • Existing issues have been referenced (where applicable)
  • I have verified this change is not present in other open pull requests
  • Functionality is documented
  • All code style checks pass
  • New code contribution is covered by automated tests
  • All new and existing tests pass

dobrerazvan and others added 6 commits July 8, 2026 16:44
PreferredDuringSchedulingIgnoredDuringExecution has no patchMergeKey in
the Kubernetes API types, so the three-way strategic merge patch treats
it as an atomic list. Any term injected by an admission controller (e.g.
ScaleOps) is removed on every reconcile because the list in the running
pod no longer matches the desired spec.

Replace the previous sync-copy approach (which corrupted the
last-applied annotation and silently suppressed intentional CR changes)
with a CalculateOption that strips preferred affinities from both sides
of the diff before the merge is computed. The diff becomes blind to
those terms, so admission-controller additions are never fought.

Also adds annotation backfill for broker pods that pre-date the
banzaicloud.com/last-applied annotation: without it the three-way merge
degenerates to a two-way diff, producing false resource diffs. Both
behaviours are gated on the new spec.admissionWebhooksEnabled field.

12 unit/integration tests added covering deletePreferredAffinities and
the full diff path via patch.DefaultPatchMaker.Calculate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…itionally

ignorePreferredAffinities is a reconciler correctness fix, not a feature
toggle. The atomic-list issue affects any external actor that touches
preferredDuringSchedulingIgnoredDuringExecution, not just ScaleOps. The
toleration merge already follows this precedent unconditionally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…y current code

Every pod Koperator creates goes through the creation path which calls
SetLastAppliedAnnotation before r.Create. The annotation is therefore always
present on pods managed by a current build; the backfill is dead code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… param

- Extract affinityKeyPod/AntiPod/Node constants to satisfy goconst
- Change baseKafkaPod() to take no arguments to satisfy unparam

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant